﻿using System;
using System.Threading;

namespace Co9320.NamaAlert.Engine.Feeder
{
	[Obsolete]
	public interface IFeedingCounter
	{
		int GetCount(int Minutes);
		int Get5MinCount();
		int Get10MinCount();
		int Get15MinCount();
		int Get30MinCount();
		int Get60MinCount();
	}

	[Obsolete]
	internal class FeedingCounter:IFeedingCounter
	{
		private static readonly TimeSpan Resolution = new TimeSpan(0, 1, 0);
		private const int MaxCount = 60;

		private class CircularLinkedList<T>
		{
			public CircularLinkedList(int Size, T InitialValue)
			{
				if (Size < 1)
				{
					throw new ArgumentOutOfRangeException("Size");
				}

				CircularLinkedListNode<T>[] lst = new CircularLinkedListNode<T>[Size];

				for (int i = 0; i < Size; i++)
				{
					lst[i] = new CircularLinkedListNode<T>(InitialValue, null, null);

					if (i != 0)
					{
						lst[i].Previous = lst[i - 1];
					}
				}

				lst[0].Previous = lst[Size - 1];


				for (int i = 0; i < Size - 1; i++)
				{
					lst[i].Next = lst[i + 1];
				}

				lst[Size - 1].Next = lst[0];

				this.First = lst[0];
				this.Last = lst[Size - 1];
			}

			public CircularLinkedListNode<T> First
			{
				get;
				private set;
			}

			public CircularLinkedListNode<T> Last
			{
				get;
				private set;
			}

			public void AddFirst(T Value)
			{
				this.First = this.Last;
				this.Last = this.Last.Previous;
				this.First.Value = Value;
			}
		}

		private class CircularLinkedListNode<T>
		{
			internal CircularLinkedListNode(T Value,
				CircularLinkedListNode<T> Next, CircularLinkedListNode<T> Previous)
			{
				this.Value = Value;
				this.Next = Next;
			}

			public T Value
			{
				get;
				set;
			}

			public CircularLinkedListNode<T> Next
			{
				get;
				internal set;
			}

			public CircularLinkedListNode<T> Previous
			{
				get;
				internal set;
			}

		}



		private CircularLinkedList<int> InnerList_;
		private DateTime Pivot_;
		private int Buffer_;
		private ReaderWriterLock Lock_;

		public FeedingCounter()
		{
			InnerList_ = new CircularLinkedList<int>(MaxCount, 0);
			Buffer_ = 0;
			Pivot_ = DateTime.MinValue;
			Lock_ = new ReaderWriterLock();
		}

		public void InclimentCount()
		{
			if (Pivot_ == DateTime.MinValue)
			{
				Pivot_ = DateTime.Now;
				Buffer_++;
			}
			else
			{
				Lock_.AcquireWriterLock(-1);

				try
				{
					DateTime Current = DateTime.Now;
					long tmp = Current.Ticks - Pivot_.Ticks;
					tmp = tmp / Resolution.Ticks;

					if (tmp == 0)
					{
						Buffer_++;
					}
					else
					{
						InnerList_.AddFirst(Buffer_);

						for (int i = 1; i < tmp; i++)
						{
							InnerList_.AddFirst(0);
						}

						Buffer_ = 1;
						Pivot_ = Current;
					}
				}
				finally
				{
					Lock_.ReleaseWriterLock();
				}
			}

			return;
		}

		public int GetCount(int Minutes)
		{
			Lock_.AcquireReaderLock(-1);

			try
			{
				if (Minutes < 1 || Minutes > MaxCount)
				{
					throw new ArgumentOutOfRangeException("Minutes");
				}

				int buff = 0;
				CircularLinkedListNode<int> cursor = InnerList_.First;

				for (int i = 0; i < Minutes; i++)
				{
					buff += cursor.Value;
					cursor = cursor.Next;
				}

				return buff;
			}
			finally
			{
				Lock_.ReleaseReaderLock();
			}

		}

		public int Get5MinCount()
		{
			return GetCount(5);
		}

		public int Get10MinCount()
		{
			return GetCount(10);
		}

		public int Get15MinCount()
		{
			return GetCount(15);
		}

		public int Get30MinCount()
		{
			return GetCount(30);
		}

		public int Get60MinCount()
		{
			return GetCount(60);
		}



	}


}
